#ifndef __THREAD_THREAD_H
#define __THREAD_THREAD_H

#include "list.h"
#include "stdint.h"
#include "string.h"
#include "global.h"
#include "memory.h"
#include "interrupt.h"
#include "debug.h"
#include "print.h"

typedef void thread_func(void*);

/*进程或线程的状态*/
enum task_status{
    TASK_RUNNING,
    TASK_READY,
    TASK_BLOCKED,
    TASK_WAITING,
    TASK_HANGING,
    TASK_DIED
};

/*中断栈 保护上下文环境*/
struct intr_stack{
    uint32_t vec_no; // kernel.asm中 push %1压入的中断号
    uint32_t edi;
    uint32_t esi;
    uint32_t ebp;
    uint32_t esp_dummy;

    uint32_t ebx;
    uint32_t edx;
    uint32_t ecx;
    uint32_t eax;

    uint32_t gs;
    uint32_t fs;
    uint32_t es;
    uint32_t ds;

//以下由cpu从低特权级到高特权级
    uint32_t err_code;
    void (*eip) (void);
    uint32_t cs;
    uint32_t eflags;
    void* esp;
    uint32_t ss;
};

/*线程栈*/
struct thread_stack{
    uint32_t ebp;
    uint32_t ebx;
    uint32_t edi;
    uint32_t esi;
/*线程第一次执行时，eip指向带调用的函数kernel_thread
  其他时候，eip是指向switch_to的返回地址*/
    void (*eip) (thread_func* func, void* func_arg);

//以下供第一次被调度上cpu时使用
    void (*unused_retaddr);
    thread_func* function; //kernel_thread所调用的函数名
    void* func_arg; //kernel_thread所调用的函数所需的参数
};

//进程或线程的pcb，程序控制块
struct task_struct{
    uint32_t* self_kstack; //各内核线程都用自己的内核栈
    enum task_status status;
    char name[16];
    uint8_t priority; //线程优先级
    uint8_t ticks; // 每次在处理器上执行的时间嘀嗒数

/* 此任务自上cpu运行后至今占用了多少cpu嘀嗒数，
    也就是此任务执行了多久*/
    uint32_t elapsed_ticks;

    /*用于线程在一般的队列中的结点*/
    struct list_elem general_tag;
    /*用于线程队列thread_all_list中的结点*/
    struct list_elem all_list_tag;

    uint32_t* pgdir; // 进程自己页表的虚拟地址

    struct virtual_addr userprog_vaddr; //用户进程的虚拟地址

    uint32_t stack_magic; //栈的边界标记，用于检测栈的溢出
};

extern struct list thread_ready_list; // 就绪队列

extern struct list thread_all_list; // 所有任务队列

void init_thread(struct task_struct* pthread, char* name, int prio);

void thread_create(struct task_struct* pthread, thread_func function, void* func_arg);

struct task_struct* thread_start(char* name, int prio, \
                    thread_func function, void* func_arg);
struct task_struct* running_thread(void);

void thread_block(enum task_status stat);

void thread_unblock(struct task_struct* pthread);

void thread_init(void);

void schedule(void);
#endif